home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 101-125 / disk_108 / tek / script.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  17KB  |  733 lines

  1. /*************************************************************
  2.  * vt100 terminal emulator - Script file support
  3.  *
  4.  *    v2.65       NG  - added tek4014 emulation
  5.  *    v2.6 870227 DBW - bug fixes for all the stuff in v2.5
  6.  *    v2.5 870214 DBW - more additions (see readme file)
  7.  *    v2.4 861214 DBW - lots of fixes/additions (see readme file)
  8.  *    v2.3 861101 DBW - minor bug fixes
  9.  *    v2.2 861012 DBW - more of the same
  10.  *    v2.1 860915 DBW - new features (see README)
  11.  *         860901 ACS - Added BAUD, PARITY and WORD commands & handling
  12.  *         860823 DBW - Integrated and rewrote lots of code
  13.  *         860815 Steve Drew: Initial version written of SCRIPT.C
  14.  *    v2.0 860809 DBW - Major rewrite
  15.  *    v1.1 860720 DBW    - Switches, 80 cols, colors, bug fixes
  16.  *    v1.0 860712 DBW    - First version released
  17.  *
  18.  *************************************************************/
  19.  
  20. #include "vt100.h"
  21.  
  22. struct COMMAND {
  23.     void (*func)();
  24.     char *cname;
  25.     };
  26.  
  27. struct LABEL  {
  28.     struct LABEL *next;
  29.     char *name;
  30.     long pos;
  31.     };
  32.  
  33. extern long atol();
  34.  
  35. /****************  globals  needed  ******************/
  36.  
  37. char        on_string[20];       /* string to match on for on cmd    */
  38. char         wait_string[20];     /* string to match of for wait cmd  */
  39. char         golabel[20];         /* label we are looking for in goto */
  40. char         on_cmd[20];          /* command to execute when on matchs*/
  41. int         onsize;             /* size of on_string                */
  42. int         waitsize;            /* size of wait_string              */
  43. int         onpos;               /* position in on string for search */
  44. int         waitpos;             /* pos in wait_string for search    */
  45. int         on_match;            /* flag set while doing on_cmd      */
  46. FILE         *sf;                 /* file pointer for script file     */
  47. struct LABEL     *lbase = NULL;       /* will point to first label     */
  48. struct LABEL     *labels;             /* current label pointer         */
  49.  
  50. /********************** command tables *******************************/
  51. static struct COMMAND inicmds[] = {    /* initialization commands */
  52.     cmd_bkg,    "bac",        /* set background color        */
  53.     cmd_bold,    "bol",        /* set bold color         */
  54.     cmd_buf,    "buf",        /* set buffer size         */
  55.     cmd_cursor,    "cur",        /* set cursor color        */
  56.     cmd_depth,    "dep",        /* set screen depth         */
  57.     cmd_fore,    "for",        /* set foreground color        */
  58.     cmd_inter,    "int",        /* interlace ON/OFF        */
  59.     cmd_lines,    "lin",        /* num lines             */
  60.     cmd_screen,    "scr",        /* Screen WB/CUST         */
  61.     cmd_volume,    "vol",        /* set volume            */
  62.     cmd_wb,    "wb",        /* use WB colors        */
  63.     cmd_null,   NULL        /* mark the end of the list */
  64.     };
  65. static struct COMMAND scrcmds[] = {    /* script only commands */
  66.     cmd_as,     "asc",        /* ascii send               */
  67.     cmd_beep,    "bee",        /* Beep                */
  68.     cmd_cap,    "cap",        /* ascii capture on/off     */
  69.     cmd_cd,     "cd",        /* change directory        */
  70.     cmd_delay,  "del",        /* delay amount of seconds  */
  71.     cmd_goto,   "got",        /* goto label               */
  72.     cmd_kb,    "kb",        /* kermit bye (for server)  */
  73.     cmd_kg,     "kg",           /* kermit get file          */
  74.     cmd_kr,     "kr",           /* kermit receive file      */
  75.     cmd_ks,     "ks",           /* kermit send file         */
  76.     cmd_on,     "on",         /* on a 'string' do a cmd   */
  77.     cmd_sb,     "sb",        /* Send a break            */
  78.     cmd_send,   "send",         /* send string to host      */
  79.     cmd_wait,   "wait",         /* wait for a host string   */
  80.     cmd_xr,     "xr",           /* xmodem receive file      */
  81.     cmd_xs,     "xs",           /* xmodem send file         */
  82.     cmd_null,   NULL        /* mark the end of the list */
  83.     };
  84. static struct COMMAND commands[]= {    /* generally available commands */
  85.     cmd_appcur,    "app",        /* turn app. cursor on/off  */
  86.     cmd_baud,   "bau",        /* Set Baud Rate            */
  87.     cmd_bt,     "bre",        /* Set Break Time        */
  88.     cmd_conv,    "con",        /* convert bs to del        */
  89.     cmd_echo,    "ech",        /* turn echo on or off        */
  90.     cmd_exit,   "exi",        /* exit script file         */
  91.     cmd_fnc,    "f",        /* define function key        */
  92.     cmd_key,    "key",        /* keyscript character        */
  93.     cmd_mode,    "mod",        /* KERMIT transfer mode        */
  94.     cmd_numkey,    "numkey",    /* turn numeric kpad on/off */
  95.     cmd_parity, "parity",    /* Set Parity            */
  96.     cmd_swap,    "swap",        /* Swap BS and DEL        */
  97.     cmd_wrap,    "wrap",        /* turn wrap on or off        */
  98.     cmd_null,   NULL        /* mark the end of the list */
  99.     };
  100.  
  101. /********************************************************************/
  102. /* checks char to see if match with on string or wait_string        */
  103. /* if on string match oncmd gets executed imediately,               */
  104. /* if wait_string match script_wait is set.                         */
  105. /********************************************************************/
  106.  
  107. chk_script(c)
  108. char c;
  109.     {
  110.     if (on_string[0] != '\0') {
  111.         if (on_string[onpos] == c) {
  112.             onpos++;
  113.             if (onpos == onsize) {
  114.                 on_match = TRUE;
  115.                 do_script_cmd(ONCOMMAND); 
  116.                 on_match = FALSE;
  117.                 return(0);
  118.         }
  119.         }
  120.         else onpos = 0;
  121.     }
  122.     if (wait_string[0] != '\0') {
  123.        if (wait_string[waitpos] != c) {
  124.             waitpos = 0;
  125.             return(0);
  126.         }
  127.         waitpos++;
  128.         if (waitpos != waitsize) return(0);
  129.         wait_string[0] = '\0';
  130.         script_wait = FALSE;
  131.     }
  132.     }
  133.  
  134. script_start(file)
  135. char *file;
  136.     {
  137.     if (strlen(file) == 0 || *file == '#') return(0);
  138.     if ((sf = fopen(file, "r")) == NULL) {
  139.         req("Can't open script file",file,0);
  140.         return(0);
  141.     }
  142.     script_on = TRUE;
  143.     script_wait = FALSE;
  144.     wait_string[0] = '\0';
  145.     on_string[0] = '\0';
  146.     on_match = FALSE;
  147.     lbase = NULL;
  148.     }
  149.  
  150. /* return pointer to next word. set l to size of the word */
  151.  
  152. char *next_wrd(s,l)
  153. char *s;
  154. int *l;
  155.     {
  156.     char *p;
  157.  
  158.     while(*s && (*s == ' ' || *s == '\t')) s++;
  159.     p = s;
  160.     while(*s && (*s != ' ' && *s != '\t')) s++;
  161.     *l = s-p;
  162.     return(p);
  163.     }
  164.  
  165. exe_cmd(p,l)
  166. char *p;
  167. int l;
  168.     {
  169.     int i,l2;
  170.  
  171.     /* downcase the command */
  172.     for (i=0; i<l; i++) p[i] |= ' ';    
  173.  
  174.     /* now search for it (first in the init command list) */
  175.     if (doing_init)
  176.     for (i=0; inicmds[i].func != cmd_null; ++i) {
  177.         l2 = strlen(inicmds[i].cname);
  178.         if (l >= l2 && strncmp(p, inicmds[i].cname, l2) == 0) {
  179.         (*inicmds[i].func)(next_wrd(p+l, &l));
  180.         return(TRUE);
  181.         }
  182.         }
  183.  
  184.     /* or the script command list */
  185.     else
  186.     for (i=0; scrcmds[i].func != cmd_null; ++i) {
  187.         l2 = strlen(scrcmds[i].cname);
  188.         if (l >= l2 && strncmp(p, scrcmds[i].cname, l2) == 0) {
  189.         (*scrcmds[i].func)(next_wrd(p+l, &l));
  190.         return(TRUE);
  191.         }
  192.         }
  193.  
  194.     /* now search for it (in the standard command list) */
  195.     for (i=0; commands[i].func != cmd_null; ++i) {
  196.     l2 = strlen(commands[i].cname);
  197.         if (l >= l2 && strncmp(p, commands[i].cname, l2) == 0) {
  198.             (*commands[i].func)(next_wrd(p+l, &l));
  199.             return(TRUE);
  200.         }
  201.     }
  202.  
  203.     /* now search in the tek command list        */
  204.     if(exe_t_cmd(p,l) == 1)
  205.         return(TRUE);
  206.  
  207.     if (doing_init) {
  208.     puts("INIT - unknown command:");
  209.     puts(p);
  210.     }
  211.     else req("Script - unknown command:",p,0);
  212.  
  213.     return(FALSE);
  214.     }
  215.  
  216. struct LABEL *find_label(lname)
  217. char *lname;
  218.     {
  219.     struct LABEL *label;
  220.   
  221.     label = lbase;
  222.     while(label != NULL) {
  223.     if (strcmp(label->name, lname) == 0) return (label);
  224.     label = label->next;
  225.     }
  226.     return(NULL);
  227.     }
  228.  
  229. do_script_cmd(stat)
  230. int stat;
  231.     {
  232.     int len,l;
  233.     char line[256];
  234.     char *p;
  235.  
  236.     /* if ON command is matched and we were     */
  237.     /* doing a DELAY then abort the delay timer,*/
  238.     /* except if on_cmd was just a SEND.        */
  239.     if (stat == ONCOMMAND) {
  240.         strcpy(line,on_cmd);
  241.         p = next_wrd(line,&l);
  242.     if (*p != 'S' && script_wait == WAIT_TIMER)  {
  243.             AbortIO((char *) &Script_Timer);
  244.             Wait (1L << Script_Timer_Port->mp_SigBit);
  245.  
  246.         /* script will proceed after on command    */
  247.             script_wait = FALSE;
  248.         }
  249.     exe_cmd(p,l);
  250.         return(0);
  251.     }
  252.     script_wait = FALSE;
  253.     while(fgets(line,256,sf) != NULL) {
  254.        len = strlen(line);
  255.        line[--len] = '\0';
  256.        p = next_wrd(&line[0], &l);
  257.        if (*(p + l - 1) == ':') {           /* its a label */
  258.            *(p + l - 1) = '\0';
  259.            if (find_label(p) == NULL) {       /* it's a new label */
  260.         if (lbase == NULL)  {          /* it's the first label */
  261.             labels = lbase = (struct LABEL *) 
  262.             malloc(sizeof (struct LABEL));
  263.             }
  264.         else {
  265.             labels->next = (struct LABEL *)
  266.             malloc(sizeof (struct LABEL));
  267.             labels = labels->next;
  268.             }
  269.         labels->pos  = ftell(sf);
  270.         labels->name = malloc(l);
  271.         labels->next = NULL;
  272.         strcpy(labels->name, p);
  273.         if (stat == GOTOLABEL && strcmp(p, golabel) == 0) 
  274.                       stat = NEXTCOMMAND;
  275.         }
  276.         p = next_wrd(p+l+1, &l);
  277.         }     /* end of it's a label */
  278.     if (stat == GOTOLABEL || *p == '#') continue;
  279.     if (*p) exe_cmd(p,l);
  280.     return(0);
  281.     }         /* end of while */
  282.     if (stat == GOTOLABEL) req("Script - label not found: ",golabel,0);
  283.     exit_script();
  284.     }
  285.  
  286. exit_script()
  287.     {
  288.     if (script_wait == WAIT_TIMER)      /* timer not done yet */
  289.        AbortIO((char *) &Script_Timer); /* so abort it */
  290.     req("Script - terminated","",0);    
  291.     script_on = FALSE;
  292.     script_wait = TRUE;
  293.     fclose(sf);
  294.     }
  295.  
  296. /* remove quotes terminate string & return pointer to start */
  297.  
  298. char *tostring(ptr)
  299. char *ptr;
  300.     {
  301.     char *s1,*s2;
  302.  
  303.     s1 = ptr;
  304.     if (*ptr == '"') {
  305.         while(*ptr++  && *ptr != '"') ;
  306.         if (*ptr == '"') {
  307.             *ptr = '\0';  
  308.             ptr = s2 = ++s1;
  309.             while(*s2) {
  310.         if    (*s2 != '^')     *s1++ = *s2;
  311.         else if (*(s2+1) == '^') *s1++ = *s2++;
  312.         else             *s1++ = ((*++s2)|' ')-96;
  313.         s2++;
  314.         }
  315.         *s1 = '\0';
  316.             return(ptr);
  317.         }
  318.     }
  319.     if (*s1 == '^') {
  320.         *s1 = (*(s1+1)|' ')-96;
  321.         *(s1+1) = '\0';
  322.         return(s1);
  323.         }
  324.     *(s1+1) = '\0';
  325.     return(s1);
  326.     }   
  327.  
  328. /***************************** SCRIPT COMMANDS ********************/
  329.  
  330. void cmd_goto(lname)
  331. char *lname;
  332.     {
  333.     struct LABEL *label;
  334.                            /* if on_cmd was a goto kill wait state */
  335.     if (on_match) { wait_string[0] = '\0'; script_wait = FALSE; }
  336.     if ((label = find_label(lname)) == NULL) {  /* is it forward */
  337.         strcpy(golabel,lname);
  338.         do_script_cmd(GOTOLABEL);
  339.     }
  340.     else {
  341.         fseek(sf,(long)(label->pos),0);
  342.     }
  343.     }
  344.  
  345. void cmd_send(str)
  346. char *str;
  347.     {
  348.     sendstring(tostring(str));
  349.     }
  350.  
  351. void cmd_wait(str)
  352. char *str;
  353.     {
  354.     str = tostring(str);
  355.     *(str+20) = '\0';         /* 20 characters max */
  356.     strcpy(wait_string, str);
  357.     waitsize = strlen(str);
  358.     script_wait = WAIT_STRING;
  359.     }
  360.  
  361. void cmd_on(str)
  362. char *str;
  363.     {
  364.    char *p;
  365.  
  366.     p = tostring(str);
  367.     strcpy(on_string, p);
  368.     onsize = strlen(p);
  369.     *(p+onsize+2+20) = '\0';        /* 20 characters max */
  370.     strcpy(on_cmd,p+onsize+2);
  371.     }
  372.  
  373. void cmd_delay(seconds)
  374. char *seconds;
  375.     {
  376.     script_wait = WAIT_TIMER;
  377.     Script_Timer.tr_time.tv_secs = atoi(seconds);
  378.     Script_Timer.tr_time.tv_micro = 0;
  379.     SendIO((char *) &Script_Timer.tr_node);
  380.     }
  381.  
  382. void cmd_exit(option)
  383. char *option;
  384.     {
  385.     char *p;
  386.     int  l;
  387.  
  388.     if (doing_init) return;
  389.  
  390.     if (*option) {
  391.     p = next_wrd(option,&l);
  392.     *(p+l) = '\000';
  393.     if  (strcmp(p,"vt100") == 0 || strcmp(p,"VT100") == 0)
  394.         cleanup("Exit vt100 from script",0);
  395.     exit_script();
  396.     script_start(p);
  397.     }
  398.     else exit_script();
  399.     }
  400.  
  401. void cmd_ks(file)
  402. char *file;
  403.     {
  404.     multi_xfer(file, doksend, 1);
  405.     }
  406.  
  407. void cmd_kr(file)
  408. char *file;
  409.     {
  410.     multi_xfer(file, dokreceive, 0);
  411.     }
  412.  
  413. void cmd_kg(file)
  414. char *file;
  415.     {
  416.     server = TRUE;
  417.     multi_xfer(file, dokreceive, 0);
  418.     }
  419.  
  420. void cmd_kb()
  421.     {
  422.     saybye();
  423.     }
  424.  
  425. void cmd_xs(file)
  426. char *file;
  427.     {
  428.     multi_xfer(file, XMODEM_Send_File, 1);
  429.     }
  430.  
  431. void cmd_xr(file)
  432. char *file;
  433.     {
  434.     multi_xfer(file, XMODEM_Read_File, 1);
  435.     }
  436.  
  437. void cmd_cap(file)
  438. char *file;
  439.     {
  440.     do_capture(file);
  441.     }
  442.  
  443. void cmd_as(file)
  444. char *file;
  445.     {
  446.     do_send(file);
  447.     }
  448.  
  449. void cmd_cd(name)
  450. char *name;
  451.     {
  452.     set_dir(name);
  453.     }
  454.  
  455. void cmd_sb(str)
  456. char *str;
  457.     {
  458.     sendbreak();
  459.     }
  460.  
  461. void cmd_baud(rate)
  462. char *rate;
  463.     {
  464.     int i = atoi(rate);
  465.  
  466.     switch( i )
  467.     {
  468.     case  300:
  469.     case 1200:
  470.     case 2400:
  471.     case 4800:
  472.     case 9600:
  473.     if (doing_init) p_baud = i;
  474.     else            setserbaud(i, TRUE);
  475.     break;
  476.  
  477.     default:
  478.     if (doing_init) {
  479.         puts("INIT - invalid baud rate:");
  480.         puts(rate);
  481.         }
  482.     else req("Script - invalid baud rate: ",rate,0);
  483.     break;
  484.     }
  485.     }
  486.  
  487. void cmd_parity(par)
  488. char *par;
  489.     {
  490.     int i;
  491.  
  492.     switch( *par|' ' )
  493.     {
  494.     case 'n': i =  0; break;
  495.     case 'm': i =  1; break;
  496.     case 's': i =  2; break;
  497.     case 'e': i =  3; break;
  498.     case 'o': i =  4; break;
  499.  
  500.     default:
  501.     if (doing_init) {
  502.         puts("INIT - invalid parity:");
  503.         puts(par);
  504.         }
  505.     else req("Script - invalid parity: ",par,0);
  506.     return;
  507.     }
  508.     p_parity = i;
  509.     if (doing_init) return;
  510.  
  511.     ClearMenuStrip( mywindow );         /* Remove old menu */
  512.     InitCommItems();                    /* Re-do comm menu   */
  513.     SetMenuStrip(mywindow,&menu[0]);    /* Re-display the menu */    
  514.     }
  515.  
  516. void cmd_bt(breaklength)
  517. char *breaklength;
  518.     {
  519.     p_break = atol(breaklength);
  520.     if (doing_init) return;
  521.  
  522.     AbortIO(Read_Request);
  523.     Read_Request->io_BrkTime = Write_Request->io_BrkTime = p_break;
  524.     setparams();
  525.     }
  526.  
  527. void cmd_mode(tmode)
  528. char *tmode;
  529.     {
  530.     switch (*tmode|' ') {
  531.     case 'i':
  532.     p_mode = 0;
  533.     break;
  534.  
  535.     case 'c':
  536.     p_mode = 1;
  537.     break;
  538.  
  539.     default:
  540.     if (doing_init) {
  541.         puts("INIT - invalid transfer mode: ");
  542.         puts(tmode);
  543.         }
  544.     else req("Script - invalid transfer mode: ",tmode,0);
  545.     return;
  546.     }
  547.     if (doing_init) return;
  548.  
  549.     ClearMenuStrip(mywindow);
  550.     InitCommItems();                    /* Re-do comm menu   */
  551.     SetMenuStrip(mywindow,&menu[0]);
  552.     }
  553.  
  554. void cmd_beep(dummy)
  555. char    *dummy;
  556.     {
  557.     if (p_volume == 0) DisplayBeep(NULL);
  558.     else {
  559.     BeginIO(&Audio_Request);
  560.     WaitIO(&Audio_Request);
  561.     }
  562.     }
  563.  
  564. void setvar(par,typ,var)
  565. char    *par;
  566. int    typ,*var;
  567.     {
  568.     int    i;
  569.  
  570.     switch (typ) {
  571.     case 0: /* ON/OFF or YES/NO */
  572.     case 1: /* not case */
  573.     if ((par[1]|' ') == 'n' || (par[0]|' ') == 'y') *var = 1-typ;
  574.     else                        *var = typ;
  575.     break;
  576.  
  577.     case 2: /* read hex number */
  578.     if (sscanf(par,"%x",&i) == 1) *var = i;
  579.         
  580.     break;
  581.  
  582.     case 3: /* read decimal number */
  583.     if (sscanf(par,"%d",&i) == 1) *var = i;
  584.     break;
  585.     }
  586.     }
  587.  
  588. void cmd_echo(par)
  589. char    *par;
  590.     {
  591.     setvar(par,0,&p_echo);
  592.     if (doing_init == 0) redoutil();
  593.     }
  594.  
  595. void cmd_wrap(par)
  596. char    *par;
  597.     {
  598.     setvar(par,0,&p_wrap);
  599.     if (doing_init == 0) redoutil();
  600.     }
  601.  
  602. void cmd_numkey(par)
  603. char    *par;
  604.     {
  605.     setvar(par,1,&p_keyapp);
  606.     if (doing_init == 0) redoutil();
  607.     }
  608.  
  609. void cmd_appcur(par)
  610. char    *par;
  611.     {
  612.     setvar(par,0,&p_curapp);
  613.     if (doing_init == 0) redoutil();
  614.     }
  615.  
  616. void cmd_swap(par)
  617. char    *par;
  618.     {
  619.     setvar(par,0,&p_bs_del);
  620.     if (doing_init == 0) redoutil();
  621.     }
  622.  
  623. void cmd_bkg(par)
  624. char    *par;
  625.     {
  626.     setvar(par,2,&p_background);
  627.     }
  628.  
  629. void cmd_bold(par)
  630. char    *par;
  631.     {
  632.     setvar(par,2,&p_bold);
  633.     }
  634.  
  635. void cmd_buf(par)
  636. char    *par;
  637.     {
  638.     setvar(par,3,&p_buffer);
  639.     }
  640.  
  641. void cmd_cursor(par)
  642. char    *par;
  643.     {
  644.     setvar(par,2,&p_cursor);
  645.     }
  646.  
  647. void cmd_depth(par)
  648. char    *par;
  649.     {
  650.     setvar(par,3,&p_depth);
  651.     }
  652.  
  653. void cmd_fore(par)
  654. char    *par;
  655.     {
  656.     setvar(par,2,&p_foreground);
  657.     }
  658.  
  659. void cmd_inter(par)
  660. char    *par;
  661.     {
  662.     setvar(par,0,&p_interlace);
  663.     }
  664.  
  665. void cmd_lines(par)
  666. char    *par;
  667.     {
  668.     setvar(par,3,&p_lines);
  669.     }
  670.  
  671. void cmd_screen(par)
  672. char    *par;
  673.     {
  674.     if ((par[0]|' ') == 'w') p_screen = 0;
  675.     else             p_screen = 1;
  676.     }
  677.  
  678. void cmd_wb(par)
  679. char    *par;
  680.     {
  681.     setvar(par,0,&p_wbcolors);
  682.     }
  683.  
  684. void cmd_key(par)
  685. char    *par;
  686.     {
  687.     int    i;
  688.  
  689.     if (sscanf(par,"%x",&i) == 1) p_keyscript = (char)(i & 0x7f);
  690.     }
  691.  
  692. void cmd_volume(par)
  693. char    *par;
  694.     {
  695.     setvar(par,3,&p_volume);
  696.     }
  697.  
  698. void cmd_conv(par)
  699. char    *par;
  700.     {
  701.     setvar(par,0,&p_bs_del);
  702.     if (doing_init == 0) redoutil();
  703.     }
  704.  
  705. void cmd_fnc(par)
  706. char    *par;
  707.     {
  708.     char    *s;
  709.     int        l;
  710.     int        i = atoi(par);
  711.  
  712.     s = par;
  713.     if (*s) s = next_wrd(s,&l);        /* skip key number */
  714.     if (*s) s = next_wrd(s+l+1,&l);    /* point at desired string */
  715.     if (*s) s = tostring(s);        /* convert the string */
  716.     if (*s && i > 0 && i < 21) {
  717.     if (i > 10) {
  718.         p_F[i-11] = malloc(strlen(s)+1);
  719.         strcpy(p_F[i-11],s);
  720.         }
  721.     else {
  722.         p_f[i-1] = malloc(strlen(s)+1);
  723.         strcpy(p_f[i-1],s);
  724.         }
  725.     }
  726.     }
  727.  
  728. void cmd_null(dummy)
  729. char *dummy;
  730.     {
  731.     }
  732.  
  733.